import random
from ev import Script, Command, CmdSet, create_object, utils
from game.gamesrc.objects.room import MyRoom
from game.gamesrc.objects.lights import LightSource


#-----------------------------------------------------------------------------------
#
# Dark Room - a scripted room
#
# This room limits the movemenets of its denizens unless they carry a and active 
# LightSource object (LightSource is defined in tutorialworld.objects.LightSource)
#
#-----------------------------------------------------------------------------------

class CmdLookDark(Command):
    """
    Look around in darkness
    
    Usage:
      look

    Looks in darkness
    """
    key = "look"
    aliases = ['l', 'guarda']
    locks = "cmd:all()"
    help_category = "General"

    def func(self):
        "Implement the command."
        caller = self.caller
        # we don't have light, grasp around blindly. 
        messages = ("E' buio. Non vedi nulla attorno a te.",
                    "Non si vede nulla! Attento potresti andare a sbattere contro qualcosa!",
                    "Non puoi vedere niente! Ti muovi nel buio senza capire dove sei.",
                    "E' completamente buio. Non hai la minima idea di quello che ti circonda.",
                    "Il buio e' cosi' fitto da renderti completamente cieco.",
                    "Ti trovi completamente al buio. Non si vede nulla.",
                    "E' buio! Non vedi ad un palmo dal tuo naso.",
                    "Sei nell'oscurita' piu' completa.",
                    "Sei avvolto dalle tenebre.")        
        irand = random.randint(0, 8)
        caller.msg(messages[irand])
        # check so we don't already carry a lightsource. 
        carried_lights = [obj for obj in caller.contents if utils.inherits_from(obj, LightSource)]
        if carried_lights:
            string = "Non vuoi restare nella cecita' piu' completa. Hai una luce, accendila!"
            caller.msg(string)



class CmdDarkHelp(Command):
    """
    Help command for the dark state.
    """
    key = "help"
    locks = "cmd:all()"
    help_category = "TutorialWorld"
    def func(self):
        "Implements the help command."
        string = "Senza una luce non possiamo aiutarti!"
        self.caller.msg(string)

# the nomatch system command will give a suitable error when we cannot find the normal commands. 
from src.commands.default.syscommands import CMD_NOMATCH
from src.commands.default.general import CmdSay
class CmdDarkNoMatch(Command):
    "This is called when there is no match"
    key = CMD_NOMATCH
    locks = "cmd:all()"
    def func(self):
        "Implements the command."
        self.caller.msg("Senza una luce non c'e' molto che tu possa fare.")

class DarkCmdSet(CmdSet):
    "Groups the commands."
    key = "darkroom_cmdset"
    mergetype = "Replace" # completely remove all other commands
    def at_cmdset_creation(self):
        "populates the cmdset."
        self.add(CmdLookDark())
        self.add(CmdDarkHelp())
        self.add(CmdDarkNoMatch())
        self.add(CmdSay())
        from game.gamesrc.commands.directions import *
        self.add(CmdDown())
        self.add(CmdEast())
        self.add(CmdNorth())
        self.add(CmdSouth())
        self.add(CmdWest())
        self.add(CmdUp())
#
# Darkness room two-state system 
#

class DarkState(Script):
    """
    The darkness state is a script that keeps tabs on when 
    a player in the room carries an active light source. It places 
    a new, very restrictive cmdset (DarkCmdSet) on all the players
    in the room whenever there is no light in it. Upon turning on 
    a light, the state switches off and moves to LightState. 
    """
    def at_script_creation(self):
        "This setups the script"
        self.key = "darkness_state"
        self.desc = "A dark room"
        self.persistent = True         
    def at_start(self): 
        "called when the script is first starting up."
        for char in [char for char in self.obj.contents if char.has_player]:
            if char.is_superuser:
                char.msg("Sei il Superuser, il buio non ha effetto su di te.")
            else:   
                char.cmdset.add(DarkCmdSet)
            char.msg("E' completamente buio qui.")
    def is_valid(self):
        "is valid only as long as noone in the room has lit the lantern."
        return not self.obj.is_lit()
    def at_stop(self):
        "Someone turned on a light. This state dies. Switch to LightState."
        for char in [char for char in self.obj.contents if char.has_player]:        
            char.cmdset.delete(DarkCmdSet)        
        self.obj.db.is_dark = False
        self.obj.scripts.add(LightState)

class LightState(Script):
    """
    This is the counterpart to the Darkness state. It is active when the lantern is on.
    """
    def at_script_creation(self):
        "Called when script is first created."
        self.key = "light_state"
        self.desc = "A room lit up"
        self.persistent = True 
    def is_valid(self):
        "This state is only valid as long as there is an active light source in the room."        
        return self.obj.is_lit()
    def at_stop(self):
        "Light disappears. This state dies. Return to DarknessState."        
        self.obj.db.is_dark = True
        self.obj.scripts.add(DarkState)
       
class DarkRoom(MyRoom):
    """
    A dark room. This tries to start the DarkState script on all
    objects entering. The script is responsible for making sure it is 
    valid (that is, that there is no light source shining in the room).
    """
    def is_lit(self):
        """
        Helper method to check if the room is lit up. It checks all
        characters in room to see if they carry an active object of 
        type LightSource. 
        """        
        return any([any([True for obj in char.contents if 'LIGHT' in obj.db.flags and obj.is_active]) 
                    for char in self.contents if char.has_player])

    def at_object_creation(self):
        "Called when object is first created."
        super(DarkRoom, self).at_object_creation()
        # this variable is set by the scripts. It makes for an easy flag to look for
        # by other game elements (such as the crumbling wall in the tutorial)
        self.db.is_dark = True
        self.db.flags.append('DARK')
        # the room starts dark.
        self.scripts.add(DarkState)

    def at_object_receive(self, character, source_location):
        "Called when an object enters the room. We crank the wheels to make sure scripts are synced."
        super(DarkRoom, self).at_object_receive(character, source_location)
        if character.has_player:
            if not self.is_lit() and not character.is_superuser:
                character.cmdset.add(DarkCmdSet)
        self.scripts.validate()

    def at_object_leave(self, character, target_location):
        "In case people leave with the light, we make sure to update the states accordingly."
        character.cmdset.delete(DarkCmdSet) # in case we are teleported away
        self.scripts.validate()
